/**
 * 
 */
package com.duowan.cms.domain.template;

import java.util.Date;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.duowan.cms.common.domain.DomainObject;
import com.duowan.cms.common.domain.Page;
import com.duowan.cms.common.exception.BaseCheckedException;
import com.duowan.cms.common.util.IdManager;
import com.duowan.cms.common.util.StringUtil;
import com.duowan.cms.common.webapp.content.SpringApplicationContextHolder;
import com.duowan.cms.domain.channel.Channel;
import com.duowan.cms.domain.template.rpst.TemplateRepository;
import com.duowan.cms.dto.template.TemplateCategory;
import com.duowan.cms.dto.template.TemplateInfo;
import com.duowan.cms.dto.template.TemplateSearchCriteria;
import com.duowan.cms.dto.template.TemplateStatus;

/**
 * 
 * 页面模板
 * 
 * @author coolcooldee
 * @version 1.0
 * @created 08-10-2012 13:50:17
 */
public class Template implements DomainObject {

    private static final long serialVersionUID = -3182458856910545305L;

    /**
     * 异常码：非法的别名（别名的格式不对，或者别名已经存在，不允许重复）
     */
    public static final String INVALID_ALIAS = Template.class.getName().concat(".001");
    
    /**
     * 模板ID
     */
    private Long id;
    /**
     * 名字
     */
    private String name;

    /**
     * 说明
     */
    private String digest;

    /**
     * 模板所在频道ID
     */
    private Channel channel;

    /**
     * 创建模板用户ID
     */
    private String createUserId;

    /**
     * 最后修改模板用户ID
     */
    private String lastUpdateUserId;

    /**
     * 操作用户IP
     */
    private String userIp;

    /**
     * 操作用户代理IP
     */
    private String proxyIp;

    /**
     * 初次发表时间
     */
    private Date postTime;

    /**
     * 上一次的更新时间
     */
    private Date updateTime;

    /**
     * 上一次保存的模板内容（即目前使用的）
     */
    private String content;

    /**
     * 上两次的更新时间（用于多版本记录）
     */
    private Date updateTime2;
    /**
     * 上两次模板内容（用于多版本记录）
     */
    private String content2;

    /**
     * 上三次的更新时间（用于多版本记录）
     */
    private Date updateTime3;
    /**
     * 上三次的模板内容（用于多版本记录）
     */
    private String content3;

    /**
     * 相关联的tags
     */
    private String relatedtag;

    /**
     * 用户操作日志
     */
    private String logs;

    /**
     * 模板别名
     */
    private String alias;

    /**
     * 合作公司（多玩,迅雷,其他）
     */
    //private String cooperate;

    /**
     * 模板文本内容的编码格式（UTF-8 / GBK）
     */
    private String code;

    @Deprecated
    private Date parserTime;

    /**
     * 模板状态（普通，删除）
     */
    private TemplateStatus templateStatus;

    /**
     * 模板类别（栏目,专题,标签,最终文章,回复,关键字）
     */
    private TemplateCategory templateCategory;
    
    public Template() {

    }

    public Template(TemplateInfo templateInfo) throws BaseCheckedException {
        if(templateInfo.getId()==null)
            this.id = IdManager.generateId();
        else
            this.id = templateInfo.getId();
        this.templateStatus = TemplateStatus.NORMAL;
        this.update(templateInfo);
    }

    public void update(TemplateInfo templateInfo) throws BaseCheckedException {
        if (!StringUtil.isEmpty(templateInfo.getName())) {
            this.name = templateInfo.getName();
        }
        this.digest = templateInfo.getDigest();
        this.channel = new Channel(templateInfo.getChannelInfo());
        this.createUserId = templateInfo.getCreateUserId();
        this.lastUpdateUserId = templateInfo.getLastUpdateUserId();
        this.userIp = templateInfo.getUserIp();
        this.proxyIp = templateInfo.getProxyIp();
        this.postTime = templateInfo.getPostTime();
        /**start:注意content1,content2,content3及对应时间的赋值顺序**/
        this.content3 = this.content2;
        this.updateTime3 = this.updateTime2;
        this.content2 = this.content;
        this.updateTime2 = this.updateTime;
        this.updateTime = new Date();
        this.content = templateInfo.getContent();
        /**end:注意content1,content2,content3及对应时间的赋值顺序**/
        this.relatedtag = this.getTagFromTemplateContent(this.content);
        this.logs = templateInfo.getLogs();
        if(!this.isValidAlias( templateInfo.getAlias())){
            throw new BaseCheckedException(INVALID_ALIAS, "非法的模板别名，命名规则：别名如果是test.html或者index.html可以放在任意目录，否则只能放在/s/目录下 ");
        }
        this.alias = templateInfo.getAlias();
        //this.cooperate = templateInfo.getCooperate();
        if (!StringUtil.isEmpty(templateInfo.getCode())) {
            this.code = templateInfo.getCode();
        }
        if(templateInfo.getTemplateStatus()!=null){
            this.templateStatus = templateInfo.getTemplateStatus();
        }
        this.templateCategory = templateInfo.getTemplateCategory();
    }

    /**
     * 验证模板别名是否合法 别名必须/开头，如果非index.html页面则必须以/s/开头
     * 同时，该专区下不能有同别名的模板
     * 
     * @param alias
     * @return
     */
    public  boolean isValidAlias(String alias) {
        // 可以为空
        if (StringUtil.isEmpty(alias))
            return true;
        if(this.isExistedByAlias(alias)){ //是否已经有同别名的模板存在
            return false;
        }
        // 必须/开头
        if (!alias.startsWith("/"))
            return false;
        // 是index.html
        if (alias.endsWith("/index.html"))
            return true;
        // 是test.html
        if (alias.endsWith("/test.html"))
            return true;
        // 如果非index.html且非test.html页面则必须以/s/开头
        if (alias.startsWith("/s/"))
            return true;
       
        return false;
    }

    /**
     * 从模板内容得到相关tag
     * @param content
     * @return
     */
    private String getTagFromTemplateContent(String content) {
        if (StringUtil.isEmpty(content))
            return "";
        String tagStr = ",";
        String tempStr = "";
        //Channel channel = this.getChannelRepository().getById(this.channelId);
        if (channel == null)
            return "";
        String channelname = channel.getName();
        Pattern pattern = null;
        Matcher matcher = null;
        String regex = null;

        /*
         * 输入tag和权重起始和数量返回本频道文章列表
         * $data.getList(tag,powerfrom,powerto,start,len)或
         * $data.getList(tag,powerfrom,powerto,len)或
         * $data.getList(tag,start,len)或 $data.getList(tag,len)
         */
        regex = "data.getList\\(\"?([^\\,\"]+)\"?\\,[^\\)]+\\)";
        tagStr += getTags(regex, content, channelname, true);

        /*
         * 输入频道中文名,tag和权重起始和数量返回文章列表,以下方法的使用方法及参数获取同example1,区别为多"频道中文名"参数,
         * 便于获取其他频道的文章列表.
         * $data.getListOther(频道中文名,tag,powerfrom,powerto,start,len)或
         * $data.getListOther(频道中文名,tag,powerfrom,powerto,len)或
         * $data.getListOther(频道中文名,tag,start,len)或
         * $data.getListOther(频道中文名,tag,len)
         */
        regex = "data.getListOther\\(([^\\,]+)\\,([^\\,]+)\\,[^\\)]+\\)";
        tagStr += getTags(regex, content, channelname, false);

        /*
         * 输入tag和权重起始和数量返回本频道图片文章列表
         * $data.getPicList(tag,powerfrom,powerto,start,len)或
         * $data.getPicList(tag,powerfrom,powerto,len)或
         * $data.getPicList(tag,start,len)或 $data.getPicList(tag,len)
         */
        regex = "data.getPicList\\(\"?([^\\,\"]+)\"?\\,[^\\)]+\\)";
        tagStr += getTags(regex, content, channelname, true);

        /*
         * 输入频道中文名,tag和权重起始和数量返回本频道图片文章列表,以下方法的使用方法及参数获取同example1,区别为获取的是该频道有头图的文章列表
         * . $data.getPicListOther(频道中文名,tag,powerfrom,powerto,start,len)或
         * $data.getPicListOther(频道中文名,tag,powerfrom,powerto,len)或
         * $data.getPicListOther(频道中文名,tag,start,len)或
         * $data.getPicListOther(频道中文名,tag,len)
         */
        regex = "data.getPicListOther\\(([^\\,]+)\\,([^\\,]+)\\,[^\\)]+\\)";
        tagStr += getTags(regex, content, channelname, false);

        /*
         * 相关文章或多tag文章列表(多tag用,分开) $list=$data.getRelate($tags,显示数量)或
         * $list=$data.getRelate($tags,权重开始,权重结束,显示数量)
         */
        pattern = Pattern.compile("data.getRelate\\(\"([^\"]+)\"\\,[^\\)]+\\)", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        matcher = pattern.matcher(content);
        while (matcher.find()) {
            tempStr = matcher.group(1).trim();
            String[] b = tempStr.split(",");
            for (int i = 0; b != null && i < b.length; i++) {
                if (b[i] == null) {
                    continue;
                }
                tempStr = b[i];
                if (tagStr.indexOf("," + tempStr + ",") == -1) {
                    tagStr += tempStr + ",";
                }
            }
        }

        if (tagStr.startsWith(",")) {
            return tagStr.substring(1, tagStr.length());
        } else {
            return tagStr;
        }
    }

    /**
     * 从模板内容中，解析出标签
     * @param regex 正则表达式
     * @param templateContent 模板内容
     * @param channelname 频道名称
     * @param isGetCurrentTag 是否是获取本频道tag
     * @return
     */
    private String getTags(String regex, String templateContent, String channelname, boolean isGetCurrentTag) {
        String tagStr = "";
        String tempStr = "";
        Pattern pattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
        Matcher matcher = pattern.matcher(templateContent);
        if (isGetCurrentTag) {
            while (matcher.find()) {
                tempStr = matcher.group(1).trim();
                if (tagStr.indexOf("," + tempStr + ",") == -1) {
                    tagStr += tempStr + ",";
                }
            }
        } else {
            while (matcher.find()) {
                if (channelname.equals(matcher.group(1))) {
                    tempStr = matcher.group(2).trim();
                } else {
                    String otherChannelName = matcher.group(1).trim();
                    String otherTag = matcher.group(2).trim();
                    tempStr = otherChannelName + ":" + otherTag;
                    tempStr = tempStr.replaceAll("\"", "");
                }
                if (tagStr.indexOf("," + tempStr + ",") == -1) {
                    tagStr += tempStr + ",";
                }
            }
        }
        return tagStr;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getDigest() {
        return digest;
    }

    public void setDigest(String digest) {
        this.digest = digest;
    }

    public Channel getChannel() {
        return channel;
    }

    public void setChannel(Channel channel) {
        this.channel = channel;
    }

    public String getCreateUserId() {
        return createUserId;
    }

    public void setCreateUserId(String createUserId) {
        this.createUserId = createUserId;
    }

    public String getLastUpdateUserId() {
        return lastUpdateUserId;
    }

    public void setLastUpdateUserId(String lastUpdateUserId) {
        this.lastUpdateUserId = lastUpdateUserId;
    }

    public String getUserIp() {
        return userIp;
    }

    public void setUserIp(String userIp) {
        this.userIp = userIp;
    }

    public String getProxyIp() {
        return proxyIp;
    }

    public void setProxyIp(String proxyIp) {
        this.proxyIp = proxyIp;
    }

    public Date getPostTime() {
        return postTime;
    }

    public void setPostTime(Date postTime) {
        this.postTime = postTime;
    }

    public Date getUpdateTime() {
        return updateTime;
    }

    public void setUpdateTime(Date updateTime) {
        this.updateTime = updateTime;
    }

    public String getContent() {
        return content;
    }

    public void setContent(String content) {
        this.content = content;
    }

    public Date getUpdateTime2() {
        return updateTime2;
    }

    public void setUpdateTime2(Date updateTime2) {
        this.updateTime2 = updateTime2;
    }

    public String getContent2() {
        return content2;
    }

    public void setContent2(String content2) {
        this.content2 = content2;
    }

    public Date getUpdateTime3() {
        return updateTime3;
    }

    public void setUpdateTime3(Date updateTime3) {
        this.updateTime3 = updateTime3;
    }

    public String getContent3() {
        return content3;
    }

    public void setContent3(String content3) {
        this.content3 = content3;
    }

    public String getRelatedtag() {
        return relatedtag;
    }

    public void setRelatedtag(String relatedtag) {
        this.relatedtag = relatedtag;
    }

    public String getLogs() {
        return logs;
    }

    public void setLogs(String logs) {
        this.logs = logs;
    }

    public String getAlias() {
        return alias;
    }

    public void setAlias(String alias) {
        this.alias = alias;
    }

//    public String getCooperate() {
//        return cooperate;
//    }
//
//    public void setCooperate(String cooperate) {
//        this.cooperate = cooperate;
//    }

    public String getCode() {
        return code;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public Date getParserTime() {
        return parserTime;
    }

    public void setParserTime(Date parserTime) {
        this.parserTime = parserTime;
    }

    public TemplateStatus getTemplateStatus() {
        return templateStatus;
    }

    public void setTemplateStatus(String templateStatus) {
        this.templateStatus = TemplateStatus.getInstance(templateStatus);
    }

    public void setTemplateStatus(TemplateStatus templateStatus) {
        this.templateStatus = templateStatus;
    }

    public TemplateCategory getTemplateCategory() {
        return templateCategory;
    }

    public void setTemplateCategory(String templateCategory) {
        this.templateCategory = TemplateCategory.getInstance(templateCategory);
    }
    
    public void setTemplateCategory(TemplateCategory templateCategory) {
        this.templateCategory = templateCategory;
    }

    /**
     * 该别名是否已经有模板存在
     * @param alias
     * @return
     */
    private boolean isExistedByAlias(String alias){
        TemplateSearchCriteria criteria = new TemplateSearchCriteria();
        criteria.setChannelId(this.channel.getId());
        criteria.setPageNo(1);
        criteria.setPageSize(1);
        criteria.setExactAlias(alias);
        Page<TemplateInfo> page = this.getTemplateRepository().pageSearch(criteria);
        if(page!=null && page.getResult()!=null && !page.getResult().isEmpty() &&  !this.id.equals(page.getResult().get(0).getId()))
            return true;
        return false;
    }
    
    private TemplateRepository getTemplateRepository(){
        return SpringApplicationContextHolder.getBean("templateRepository", TemplateRepository.class);
    }

}
